#!/usr/bin/env node

/**
 * Vue + TypeScript + ESLint 快速配置脚本
 * 一键解决模块解析、路径别名、重复报错等常见问题
 * 
 * 使用方法：
 * 1. 将此文件保存到项目根目录
 * 2. 运行：node quick-setup-vue-ts-eslint.js
 * 3. 按提示完成配置
 */

const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')

// 颜色输出函数
const colors = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m'
}

function colorLog(color, message) {
  console.log(`${colors[color]}${message}${colors.reset}`)
}

// 配置模板
const CONFIG_TEMPLATES = {
  // TypeScript 配置
  'tsconfig.app.json': {
    "extends": "@vue/tsconfig/tsconfig.dom.json",
    "include": [
      "env.d.ts",
      "src/**/*",
      "src/**/*.vue"
    ],
    "exclude": [
      "src/**/__tests__/*"
    ],
    "compilerOptions": {
      "composite": true,
      "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
      "baseUrl": ".",
      "paths": {
        "@/*": ["src/*"]
      }
    }
  },

  // Vue 模块声明
  'src/vite-env.d.ts': `/// <reference types="vite/client" />

// 为 .vue 单文件组件提供模块声明，供 TypeScript 识别
// 说明：使用 DefineComponent 的默认泛型，避免使用 \`{}\` 与 \`any\` 以通过更严格的 ESLint 规则
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent
  export default component
}
`,

  // ESLint 配置
  '.eslintrc.cjs': `/*
 * ESLint 配置：与 TypeScript 规则对齐，支持 Vue 3 + <script setup> + TS
 * - 关闭 ESLint 层的未使用变量检测，交由 TypeScript 编译器（TS6133）统一处理
 * - 引入 unplugin-auto-import 生成的全局声明，避免无谓的未定义报错
 */

// 引入自动导入生成的全局变量定义
const autoImportGlobals = (() => {
  try {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const cfg = require('./.eslintrc-auto-import.json')
    return cfg.globals || {}
  } catch (e) {
    return {}
  }
})()

module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  // 使用 Vue 的解析器，转交 <script> 内容给 TS 解析器
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 'latest',
    sourceType: 'module',
    extraFileExtensions: ['.vue'],
  },
  plugins: ['vue', '@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  rules: {
    // 与 TS 编译器保持一致：未使用变量交由 TS 处理，避免重复报错
    'no-unused-vars': 'off',
    '@typescript-eslint/no-unused-vars': 'off',

    // 常见工程化约定
    'vue/multi-word-component-names': 'off',
  },
  globals: {
    ...autoImportGlobals,
  },
  ignorePatterns: [
    'dist/',
    'node_modules/',
    'src/types/*.d.ts',
  ],
}
`
}

/**
 * 检查必要依赖是否已安装
 */
function checkDependencies() {
  colorLog('blue', '📦 检查项目依赖...')
  
  if (!fs.existsSync('package.json')) {
    colorLog('red', '❌ 未找到 package.json，请确保在项目根目录运行此脚本')
    process.exit(1)
  }

  const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'))
  const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies }
  
  const requiredDeps = [
    'vue',
    '@vitejs/plugin-vue',
    'typescript',
    'vue-tsc',
    'eslint',
    '@typescript-eslint/parser',
    '@typescript-eslint/eslint-plugin',
    'eslint-plugin-vue'
  ]
  
  const missingDeps = requiredDeps.filter(dep => !allDeps[dep])
  
  if (missingDeps.length > 0) {
    colorLog('red', '❌ 缺少以下必要依赖:')
    missingDeps.forEach(dep => console.log(`   - ${dep}`))
    console.log('')
    colorLog('yellow', '💡 请先安装缺少的依赖：')
    console.log(`   npm install -D ${missingDeps.join(' ')}`)
    console.log('   或')
    console.log(`   pnpm add -D ${missingDeps.join(' ')}`)
    process.exit(1)
  }
  
  colorLog('green', '✅ 依赖检查通过')
  return packageJson
}

/**
 * 备份现有配置文件
 */
function backupExistingConfigs() {
  colorLog('blue', '💾 备份现有配置...')
  
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)
  const backupDir = `.config-backup-${timestamp}`
  
  const filesToBackup = [
    'tsconfig.app.json',
    '.eslintrc.cjs',
    '.eslintrc.js',
    '.eslintrc.json',
    'src/vite-env.d.ts'
  ]
  
  const backedUpFiles = []
  
  filesToBackup.forEach(file => {
    if (fs.existsSync(file)) {
      if (!fs.existsSync(backupDir)) {
        fs.mkdirSync(backupDir, { recursive: true })
      }
      fs.copyFileSync(file, path.join(backupDir, path.basename(file)))
      backedUpFiles.push(file)
    }
  })
  
  if (backedUpFiles.length > 0) {
    colorLog('green', `✅ 已备份 ${backedUpFiles.length} 个配置文件到: ${backupDir}`)
    backedUpFiles.forEach(file => console.log(`   - ${file}`))
    return backupDir
  } else {
    colorLog('yellow', '⚠️ 未找到需要备份的配置文件')
    return null
  }
}

/**
 * 应用配置模板
 */
function applyConfigTemplates() {
  colorLog('blue', '🔧 应用标准化配置...')
  
  // 确保 src 目录存在
  if (!fs.existsSync('src')) {
    fs.mkdirSync('src', { recursive: true })
    colorLog('green', '✅ 创建 src 目录')
  }
  
  // 应用每个配置模板
  Object.entries(CONFIG_TEMPLATES).forEach(([filename, content]) => {
    const dir = path.dirname(filename)
    
    // 创建目录（如果不存在）
    if (dir !== '.' && !fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true })
    }
    
    // 写入文件
    if (typeof content === 'object') {
      fs.writeFileSync(filename, JSON.stringify(content, null, 2) + '\n')
    } else {
      fs.writeFileSync(filename, content)
    }
    
    colorLog('green', `✅ 创建/更新: ${filename}`)
  })
}

/**
 * 验证配置是否正确
 */
function validateConfiguration(packageJson) {
  colorLog('blue', '🔍 验证配置...')
  
  const scripts = packageJson.scripts || {}
  
  // 检查 TypeScript
  if (scripts.check || scripts['type-check']) {
    try {
      const checkCmd = scripts.check || scripts['type-check']
      colorLog('cyan', `运行: ${checkCmd}`)
      execSync(checkCmd, { stdio: 'pipe' })
      colorLog('green', '✅ TypeScript 类型检查通过')
    } catch (error) {
      colorLog('yellow', '⚠️ TypeScript 检查有警告，这是正常的，可能需要清理代码中的未使用变量')
    }
  } else {
    colorLog('yellow', '⚠️ 未找到 TypeScript 检查脚本，建议在 package.json 中添加:')
    console.log('   "check": "vue-tsc -b"')
  }
  
  // 检查 ESLint
  if (scripts.lint) {
    try {
      colorLog('cyan', `运行: ${scripts.lint}`)
      execSync(scripts.lint, { stdio: 'pipe' })
      colorLog('green', '✅ ESLint 检查通过')
    } catch (error) {
      colorLog('yellow', '⚠️ ESLint 检查有警告，可运行 "npm run lint:fix" 自动修复格式问题')
    }
  } else {
    colorLog('yellow', '⚠️ 未找到 ESLint 检查脚本，建议在 package.json 中添加:')
    console.log('   "lint": "eslint . --ext .ts,.vue"')
    console.log('   "lint:fix": "eslint . --ext .ts,.vue --fix"')
  }
}

/**
 * 显示完成信息和后续建议
 */
function showCompletionInfo(backupDir) {
  console.log('')
  colorLog('green', '🎉 配置完成！')
  
  if (backupDir) {
    colorLog('cyan', `📁 原配置已备份到: ${backupDir}`)
  }
  
  console.log('')
  colorLog('blue', '🔧 可用命令：')
  console.log('   npm run check     # TypeScript 类型检查')
  console.log('   npm run lint      # ESLint 代码检查')
  console.log('   npm run lint:fix  # ESLint 自动修复格式问题')
  console.log('   npm run dev       # 启动开发服务器')
  console.log('   npm run build     # 构建生产版本')
  
  console.log('')
  colorLog('blue', '💡 接下来的步骤：')
  console.log('   1. 重启你的 IDE (VS Code 等) 以加载新配置')
  console.log('   2. 运行 "npm run lint:fix" 自动修复代码格式')
  console.log('   3. 运行 "npm run check" 确保类型检查通过')
  console.log('   4. 开始愉快地开发吧！')
  
  console.log('')
  colorLog('blue', '🚨 常见问题解决：')
  console.log('   - 如果 IDE 仍提示找不到模块，请重启 IDE')
  console.log('   - 如果路径别名不工作，检查 vite.config.ts 中的 alias 配置')
  console.log('   - 如果有未使用变量警告，运行 "npm run lint:fix" 或手动清理')
  
  if (backupDir) {
    console.log('')
    colorLog('yellow', `🔄 如需回滚配置，请从 ${backupDir} 目录恢复文件`)
  }
}

/**
 * 主函数
 */
function main() {
  console.log('')
  colorLog('magenta', '🚀 Vue + TypeScript + ESLint 快速配置工具')
  colorLog('cyan', '   解决模块解析、路径别名、重复报错等常见问题')
  console.log('')
  
  try {
    // 1. 检查依赖
    const packageJson = checkDependencies()
    
    // 2. 备份现有配置
    const backupDir = backupExistingConfigs()
    
    // 3. 应用新配置
    applyConfigTemplates()
    
    // 4. 验证配置
    validateConfiguration(packageJson)
    
    // 5. 显示完成信息
    showCompletionInfo(backupDir)
    
  } catch (error) {
    console.log('')
    colorLog('red', '❌ 配置过程中出现错误:')
    console.error(error.message)
    console.log('')
    colorLog('yellow', '💡 请检查错误信息并重试，或手动应用配置模板')
    process.exit(1)
  }
}

// 如果直接运行此脚本，执行主函数
if (require.main === module) {
  main()
}

// 导出函数供其他模块使用
module.exports = {
  checkDependencies,
  backupExistingConfigs,
  applyConfigTemplates,
  validateConfiguration,
  CONFIG_TEMPLATES
}